#tag ClassProtected Class XLIFFdocValidator	#tag Method, Flags = &h0		Sub checkAltTrans()		  'Required Attributes: alttranstype, match-quality, dx:glorious-match, dx:match-penalty, origin, dx:origin-shorttext, dx:modified-by, dx:modified-at		  'alttranstype		  'Acceptable values: "proposal", "previous-version"		  'match-quality		  'Use values 0-100. The use of decimal numbers is acceptable, but only a single digit of precision is allowed. For example, "99.5" is acceptable, but "99.52" is not. Do not use a percent sign. Higher numbers refer to better matches than lower numbers.		  'dx:glorious-match		  'Indicates whether the match is an exact, in-context match (as determined by the tool that generated the match). Acceptable values: "yes", "no". Default value: "no".		  'origin		  'Acceptable values: "TM", "MT", "XLIFF", "manual", “sourcetext”, “pseudo-trans”. See the dx:origin attribute of the <trans-unit> element for more information on how to assign and interpret these values.		  'dx:origin-shorttext		  'Human-readable string describing the match origin. This could be the name of the TM it came out of, the name of an MT engine, etc. Examples: "Master TM 1", "Google MT", "myDocument.docx.xlf".		  'dx:match-penalty		  'Use values 0-100. The use of decimal numbers is acceptable, but only a single digit of precision is allowed. For example, "0.5" is acceptable, but "0.48" is not. Do not use a percent sign. Higher numbers refer to larger penalties than lower numbers.		  'dx:modified-by		  'dx:modified-at		  		  		  // iterate through the <alt-trans> objects		  dim altItr, altCnt as integer		  dim altQ as XmlNodeList		  dim altNode as xmlnode		  altQ = me.myXLIFFxml.XQL("//alt-trans")		  altCnt = altQ.Length		  		  for altItr = 0 to altCnt - 1		    altNode = altQ.item(altItr)		    		    // get reference to the parent <trans-unit>		    dim tuid as string		    dim ancestorTUnode as xmlnode		    ancestorTUnode = altNode.parent		    // get tuid		    ancestorTUnode = getAncestorTransUnit(altNode)		    if ancestorTUnode <> nil then		      tuid = "<trans-unit> " + ancestorTUnode.GetAttribute("id")		    end if		    		    // is this version history or leveraged match?		    dim altTransType as string		    if altNode.GetAttribute("alttranstype") = "proposal" or altNode.GetAttribute("alttranstype") = "" then		      altTransType = ALT_TRANS_TYPE_PROPOSAL		    elseif altNode.GetAttribute("alttranstype") = "previous-version" then		      altTransType = ALT_TRANS_TYPE_VERSION_HISTORY		    else		      // error: illegal value		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ has a alttranstype attribute with an illegal value ($2).",tuid,altNode.GetAttribute("alttranstype")),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // check that dx:match-penalty and match-quality have single-digit precision numbers in range 0 - 100		    dim matchRateTypes(1) as string = array("match-quality","dx:match-penalty")		    dim i as integer		    for i = 0 to 1		      dim thisValue as string		      thisValue = altNode.GetAttribute(matchRateTypes(i))		      // should this <alt-trans> even have a value here?		      // it should NOT have it, if it's version history? or should it, because maybe the version that was overwritten was originally from a fuzzy or ICE match???		      if altTransType = ALT_TRANS_TYPE_VERSION_HISTORY then		        // must NOT have anything.		        if thisValue <> "" then		          // error: shouldn't have anything		          me.errorsEncountered = true		          dim newError as XLIFFdocError		          newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ has a $2$ attribute, but perhaps should not, as it is a version history <alt-trans>.",tuid,matchRateTypes(i)),ERROR_LEVEL_WARNING)		          me.myErrors.append newError		        end if		      elseif altTransType = ALT_TRANS_TYPE_PROPOSAL then		        // needs to have something, check it. (0 is also ok of course)		        dim valAsInteger as integer		        valAsInteger = val(thisValue) * 10		        if valAsInteger <> val(thisValue) * 10 then		          // proves the number has more than single digit precision		          me.errorsEncountered = true		          dim newError as XLIFFdocError		          newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ has a $2$ attribute with greater than single-digit precision ($3$).",tuid,matchRateTypes(i),thisValue),ERROR_LEVEL_ERROR)		          me.myErrors.append newError		        end if		        if valAsInteger < 0 or valAsInteger > 1000 then		          // outside of range of 0.0 to 100.0		          me.errorsEncountered = true		          dim newError as XLIFFdocError		          newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ has a $2$ attribute outside of the range of 0.0 to 100.0 ($3$).",tuid,matchRateTypes(i),thisValue),ERROR_LEVEL_ERROR)		          me.myErrors.append newError		        end if		      else		        // only would happen if something was wrong with the altTransType, and we already report that, so do nothing.		      end if		    next i		    		    // check origin against pre-defined allowed values		    dim definedMatchOrigin as string = altNode.getAttribute("origin")		    if definedMatchOrigin <> "" then		      if me.allowedMatchOrigins.IndexOf(definedMatchOrigin) < 0 then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ has an invalid match origin value: $2$",tuid,definedMatchOrigin),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    else		      // doesn't have ANY matchorigin, but must have something.		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ does not have a defined match origin",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that dx:origin-shorttext was set		    if altNode.GetAttribute("dx:origin-shorttext") = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ does not have any value set for the dx:origin-shorttext attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that dx:modified-at was set		    if altNode.GetAttribute("dx:modified-at") = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ does not have any value set for the dx:modified-at attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that dx:modified-at was set		    if altNode.GetAttribute("dx:modified-by") = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_ALT_TRANS_ELEMENT,localize.getwp("An <alt-trans> element in $1$ does not have any value set for the dx:modified-by attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		  next altItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxContext()		  '<dx:context-source-after>		  'The contents of this element are a text-only representation of the context that came after the content captured in the <source>		  'of the <alt-trans> ancestor. A maximum of 150 characters (not bytes) worth of information can be stored in this element.		  		  // nothing much to check in the parent <dx:context> object that won't be checked by an XML validation, so we'll just check that the children		  // nodes have no more than 150characters of data in them, and only 1 text node child.		  		  // iterate through the <dx:context> objects		  dim contextItr, contextCnt as integer		  dim contextQ as XmlNodeList		  dim contextNode as xmlnode		  contextQ = me.myXLIFFxml.XQL("//dx:context-source-after|//dx:context-source-before|//dx:context-target-after|//dx:context-target-before")		  contextCnt = contextQ.Length		  		  for contextItr = 0 to contextCnt - 1		    contextNode = contextQ.item(contextItr)		    dim nodeName as string		    nodeName = contextNode.name		    		    // get tuid of whatever <trans-unit> this was a grandchild of		    dim tuid as string		    dim ancestorTUnode as xmlnode		    ancestorTUnode = getAncestorTransUnit(contextNode)		    if ancestorTUnode <> nil then		      tuid = "<trans-unit> " + ancestorTUnode.GetAttribute("id")		    end if		    		    // it must contain 1 text node child.		    // more than 1 child?		    if ContextNode.ChildCount > 1 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_CONTEXT_ELEMENTS,localize.getwp("A <$1$> element in an <alt-trans> element child of $2$ has more than one child element.",nodeName,tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // first child is a text node?		    if not contextNode.FirstChild isa XmlTextNode then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_CONTEXT_ELEMENTS,localize.getwp("A <$1$> element in an <alt-trans> element child of $2$ is invalid. Only text nodes are allowed as children.",nodeName,tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    else		      // check if has more than 150 characters of size.		      dim textlength as integer = len(contextNode.FirstChild.Value)		      if textlength > 150 then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_DX_CONTEXT_ELEMENTS,localize.getwp("A <$1$> element in an <alt-trans> element child of $2$ contains $3$ characters. Only 150 are allowed.",nodeName,tuid,str(textlength)),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    end if		    		  next contextItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxInternalPreview()		  // 1 preview per <file>?		  // each preview has a call out for each TU in the <file>?		  		  dim fileItr, fileCnt as integer		  dim previewCnt as integer		  		  // 1 preview per <file>?		  dim fileQ as XmlNodeList		  fileQ = me.myXLIFFxml.XQL("//file")		  fileCnt = fileQ.Length		  dim previewQ as XmlNodeList		  previewQ = me.myXLIFFxml.XQL("//dx:internal-preview")		  previewCnt = previewQ.length		  if fileCnt <> previewCnt then		    // should be 1 preview for each file element, but there isn't.		    me.errorsEncountered = true		    dim newError as XLIFFdocError		    if previewCnt > fileCnt then		      newError = new XLIFFdocError(ERROR_CATEGORY_INTERNAL_PREVIEW,localize.getwp("Only one preview is allowed per <file> element, but this document has more previews than files."),0)		    else		      newError = new XLIFFdocError(ERROR_CATEGORY_INTERNAL_PREVIEW,localize.getwp("One or more files in this XLIFF:doc are missing a preview element."),0)		    end if		    me.myErrors.append newError		    // no point in going further with this check		    return		  end if		  		  // 1 TU callout in each preview, for each TU in that file?		  dim thePreviewNode as xmlnode		  dim theFileNode as xmlnode		  dim prevTUcnt as integer		  dim TUcnt as integer		  		  for fileItr = 0 to fileCnt - 1		    theFileNode = fileQ.item(fileItr)		    previewQ = theFileNode.XQL("header/dx:internal-preview")		    		    // maintain these per file, or the effect is cumulative		    dim previewTUids(-1) as string		    dim actualTUids(-1) as string		    dim mergedIDlist(-1) as string		    		    // 1 preview for this file node?		    if previewQ.length <> 1 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      if previewQ.length = 0 then		        // this file element doesn't have a preview		        newError = new XLIFFdocError(ERROR_CATEGORY_INTERNAL_PREVIEW,localize.getwp("This file element doesn't have a preview element: $1$",theFileNode.GetAttribute("original")),0)		      else		        // this file element has more than one preview!?		        newError = new XLIFFdocError(ERROR_CATEGORY_INTERNAL_PREVIEW,localize.getwp("This file element has more than one preview element: $1$",theFileNode.GetAttribute("original")),0)		      end if		      me.myErrors.append newError		      // no point in going further with this check		      return		    end if		    // get ids as listed in preview Node		    thePreviewNode = previewQ.item(0)		    dim previewTuQ as XmlNodeList		    previewTuQ = thePreviewNode.XQL("dx:content")		    prevTUcnt = previewTuQ.length		    if prevTUcnt > 0 then		      dim i as integer		      for i = 0 to prevTUcnt - 1		        previewTUids.append previewTuQ.item(i).getattribute("dx:id")		        mergedIDlist.append previewTuQ.item(i).getattribute("dx:id")		      next i		    end if		    // get ids of TUs listed in the <file> node.		    dim TuQ as XmlNodeList		    TuQ = theFileNode.XQL("body/group/trans-unit")		    TUcnt = TuQ.length		    if TUcnt > 0 then		      dim i as integer		      for i = 0 to TUcnt - 1		        actualTUids.append TuQ.item(i).getattribute("id")		        mergedIDlist.append TuQ.item(i).getattribute("id")		      next i		    end if		    // check for duplicates (or rather, absense of duplicates: this method will return an empty array of any IDs that did not appear more than once.		    dim listOfNonUniqueIDsBetweenPreviewAndActualTUs(-1) as string		    listOfNonUniqueIDsBetweenPreviewAndActualTUs = common.returnNonDuplicatesFromArray(mergedIDlist)		    if ubound(listOfNonUniqueIDsBetweenPreviewAndActualTUs) <> -1 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_INTERNAL_PREVIEW,localize.getwp("There is a mismatch between the TUIDs in the preview for this file element and the TUIDs in the <trans-unit> elements of this file: $1$ ($2$)",theFileNode.GetAttribute("original"),join(listOfNonUniqueIDsBetweenPreviewAndActualTUs,", ")),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		      // rather than returning here, might as well let other checks continue...		    end if		    // since we already have the list, might as well check if the TUIDs are all unique within themselves.		    dim listofNonUniqueTUIDs(-1) as string		    listofNonUniqueTUIDs = common.returnDuplicatesFromArray(actualTUids)		    if ubound(listofNonUniqueTUIDs) <> -1 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("One or more of the TUIDs in this file element are non-unique: $1$ ($2$)",theFileNode.GetAttribute("original"),join(listofNonUniqueTUIDs,", ")),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		      // rather than returning here, might as well let other checks continue...		    end if		    		  next fileItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxNote()		  'Parent Elements: <trans-unit>, <alt-trans>, <header>		  'Child Elements: none		  'Required Attributes: dx:modified-at, dx:modified-by		  'dx:modified-at		  'Time and date the <dx:note> was last modified. This can represent the date/time the note was created, edited, or processed in some other way.		  'Note: Date/time must be specified in ISO 8601 format. Time must be specified in UTC (Zulu) time zone. See the XLIFF date element for more information.		  'dx:modified-by		  'Use this attribute to indicate who created or last edited the note. This would typically be a user ID, user name, role or description.		  'Acceptable values: undefined. Must be a string value.		  'Optional Attributes: dx:annotates		  'dx:annotates		  'Notes can optionally be defined as referring to specific text in the source or target. If specific text is to be associated with the note, the dx:annotates attribute must be set, and set to either source or target.		  'Acceptable values: source, target, general. Default value: general.		  		  		  // iterate through the <dx:note> objects		  dim noteItr, noteCnt as integer		  dim noteQ as XmlNodeList		  dim noteNode as xmlnode		  noteQ = me.myXLIFFxml.XQL("//dx:note")		  noteCnt = noteQ.Length		  		  for noteItr = 0 to noteCnt - 1		    noteNode = noteQ.item(noteItr)		    		    // is this attached to a TU, and alt-trans, or a header?		    dim tuid as string		    dim ancestorTUnode as xmlnode		    dim ancestorName as string		    ancestorTUnode = noteNode.parent		    ancestorName = ancestorTUnode.localName		    if ancestorName = "trans-unit" or ancestorName = "alt-trans" then		      // get tuid		      ancestorTUnode = getAncestorTransUnit(noteNode)		      if ancestorTUnode <> nil then		        tuid = "<trans-unit> " + ancestorTUnode.GetAttribute("id")		      end if		    elseif ancestorName = "header" then		      // this is ok, but we don't have any TUID to report.		      tuid = "<header>"		    else		      // this is not ok. invalid schema.		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_NOTE_ELEMENT,localize.getwp("<dx:note> elements are not allowed as children of the <$1$> element.",ancestorName),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		      // not much point in continuing with this particular note.		      continue for noteItr		    end if		    		    // does it have at least one thing it is surrounding? it must contain some text, and nothing else.		    dim i, cnt as integer		    dim hasTextChild as boolean = false		    cnt = noteNode.ChildCount - 1		    for i = 0 to cnt		      if noteNode.child(i) isa XmlTextNode then		        hasTextChild = true		        exit for i		      end if		    next i		    if not hasTextChild then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_NOTE_ELEMENT,localize.getwp("A <dx:note> element in $1$ does not encapsulate any text nodes. The <note> element must contain at least 1 character of text.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // check that dx:modified-at was set		    if noteNode.GetAttribute("dx:modified-at") = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_NOTE_ELEMENT,localize.getwp("A <dx:note> element in $1$ does not have any value set for the dx:modified-at attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that dx:modified-at was set		    if noteNode.GetAttribute("dx:modified-by") = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_NOTE_ELEMENT,localize.getwp("A <dx:note> element in $1$ does not have any value set for the dx:modified-by attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that dx:annotates was set correctly		    dim annotatesValue as string = noteNode.GetAttribute("dx:annotates")		    if annotatesValue <> "" then		      if me.allowedAnnotateValuesForDxNote.IndexOf(annotatesValue) < 0 then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_DX_NOTE_ELEMENT,localize.getwp("A <dx:note> element in $1$ has an invalid value ($2$) set for the dx:annotates attribute.",tuid,annotatesValue),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    end if		    		  next noteItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxQaHit()		  'Required Attributes: dx:qa-origin, dx:qa-ignorable, x:qa-shorttext, dx:qa-category, dx:qa-level		  'dx:qa-origin		  'Indicates whether the QA hit originates from the source, the target, or from both. If the QA system identifies not just errors and warnings, but also non-errors (the correct thing was done by the linguist), then it can use a value of "both" here, and collapse the source-to-target hit, and the target-to-source hit into a single hit.		  'Accepted values: "source”, “target”, “both”		  'dx:qa-ignorable		  'Provides information to the tool reading the file as to whether this QA message can safely be ignored by the user. This determination is made by the tool that creates the QA message. The information must be made available to the tool user, but further behavior is not specified or required.		  'Accepted values: "yes", "no"		  'x:qa-shorttext		  'Human-readable description of the QA message. Must include specific information whenever possible, rather than a general description of the error.		  'dx:qa-category		  'Categorizes the type of QA message involved. The following table may be of assistance in matching your tool's QA categories to those supported in XLIFF:doc:		  'Acceptable values: "number", "pattern", "punctuation", "tags", "date", "time", "internationalization", "omission", "inconsistency", "terminology", "other"		  'dx:qa-level		  'Defines the degree of seriousness of the QA message.		  'Accepted values: "error" (most serious), "warning", "non-error" (proactive match/confirmation)		  'Optional Attributes: dx:qa-code, dx:qa-tgt-startpos, dx:qa-tgt-length, dx:qa-src-startpos, dx:qa-src-length		  'dx:qa-code		  'Tool-specific ID code for the error type. XLIFF:doc does not specify any limitations for the value of this optional attribute.		  'Note: this is not an ID number for the specific QA hit instance. There is no ID attribute in XLIFF:doc for a QA hit instance.		  '		  'dx:qa-tgt-startpos		  'The position, in unicode characters, from the start of the target segment, with 1 as the first position. Set to "0" if the position is unknown.		  'dx:qa-tgt-length		  'The length, in unicode characters, of the text in the target related to the QA hit. Set to "0" if the length is unknown.		  'dx:qa-src-startpos		  'The position, in unicode characters, from the start of the source segment, with 1 as the first position. Set to "0" if the position is unknown.		  'dx:qa-src-length		  'The length, in unicode characters, of the text in the source related to the QA hit. Set to "0" if the length is unknown.		  		  // iterate through the <dx:qa-hit> objects		  dim qaItr, qaCnt as integer		  dim qaQ as XmlNodeList		  dim qaNode as xmlnode		  qaQ = me.myXLIFFxml.XQL("//dx:qa-hit")		  qaCnt = qaQ.Length		  		  for qaItr = 0 to qaCnt - 1		    qaNode = qaQ.item(qaItr)		    		    // get reference to the parent <trans-unit>		    dim tuid as string		    dim ancestorTUnode as xmlnode		    // get tuid		    ancestorTUnode = getAncestorTransUnit(qaNode)		    if ancestorTUnode <> nil then		      tuid = "<trans-unit> " + ancestorTUnode.GetAttribute("id")		    end if		    		    // check that dx:qa-category is one of the allowed values		    dim definedValue as string = qaNode.getAttribute("dx:qa-category")		    if me.allowedQAcategories.IndexOf(definedValue) < 0 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_QA_HIT_ELEMENT,localize.getwp("A <dx:qa-hit> element in $1$ has an invalid dx:qa-category value: $2$",tuid,definedValue),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // check that dx:qa-level is one of the allowed values		    definedValue = qaNode.getAttribute("dx:qa-level")		    if me.allowedQaLevels.IndexOf(definedValue) < 0 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_QA_HIT_ELEMENT,localize.getwp("A <dx:qa-hit> element in $1$ has an invalid dx:qa-level value: $2$",tuid,definedValue),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // check that dx:qa-origin is one of the allowed values		    definedValue = qaNode.getAttribute("dx:qa-origin")		    if me.allowedQaOrigins.IndexOf(definedValue) < 0 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_QA_HIT_ELEMENT,localize.getwp("A <dx:qa-hit> element in $1$ has an invalid dx:qa-origin value: $2$",tuid,definedValue),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // check that dx:qa-shorttext is defined		    definedValue = qaNode.getAttribute("dx:qa-shorttext")		    if definedValue = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_QA_HIT_ELEMENT,localize.getwp("A <dx:qa-hit> element in $1$ does not define a dx:dx-shorttext value.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		  next qaItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxUtxGlossary()		  'Note: A UTX glossary in an XLIFF:doc file may only contain languages that match the languages of the XLIFF:doc itself. For example, an English to French XLIFF:doc cannot contain a UTX glossary that references German and English. However, it is permissible for a tool to reference languages that are only a match on the language, and not on the geography/culture of the XLIFF:doc. For example, an XLIFF:doc going into French for France (fr-FR) could have an embedded UTX glossary that referenced French for Canada (fr-CA) terms.		  'Example:		  '<dx:utx-glossary dx:version="1.11" dx:src-lang="en-US" dx:tgt-lang="ja-JP" dx:date-created="2011-08-17T19:00:00Z" dx:creator="Acme Corporation">...</dx:utx-glossary>		  'Parent Elements: <xliff>		  'Child Elements: <dx:utx-term>+		  'Required Attributes: dx:version, dx:src-lang, dx:tgt-lang, dx:date-created, dx:creator		  'dx:version		  'Maps to the version item in the header of the UTX file (position 1)		  'dx:src-lang		  'Maps to the source language item in the header of the UTX file (position 2 - before slash). ISO 639 and 3166 formats.		  'Note: See RFC 5646 for more information.		  'dx:tgt-lang		  'Maps to the target language item in the header of the UTX file (position 2 - after slash). ISO 639 and 3166 formats.		  'Note: See RFC 5646 for more information.		  'dx:date-created		  'Maps to the date created timestamp in the header of the UTX file (position 3). ISO 8601 format.		  'dx:creator		  'Maps to the creator item in the header of the UTX file (position 4)		  		  // iterate through the <dx:utx-glossary> objects		  dim glossItr, glossCnt as integer		  dim glossQ as XmlNodeList		  dim glossNode as xmlnode		  glossQ = me.myXLIFFxml.XQL("//xliff/dx:utx-glossary")		  glossCnt = glossQ.Length		  		  // only 0 or 1 glossaries are allowed		  if glossCnt > 1 then		    me.errorsEncountered = true		    dim newError as XLIFFdocError		    newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("This XLIFF:doc has $1$ <dx:utx-glossary> elements, but only one is allowed.",str(glossCnt)),ERROR_LEVEL_ERROR)		    me.myErrors.append newError		  end if		  		  for glossItr = 0 to glossCnt - 1		    glossNode = glossQ.item(glossItr)		    		    // do source and target (base) languages match those of the XLIFF itself?		    // assumption here that all <file> elements have the same source/target languages. we should check that when checking <file>, but don't need to check it here. just take 1st.		    		    // src/target from the UTX glossary		    dim fileSrc, fileTgt as string		    dim glossSrc, glossTgt as string		    glossSrc = glossNode.GetAttribute("dx:src-lang")		    glossTgt = glossNode.GetAttribute("dx:tgt-lang")		    		    // src/target from the first <file> element in the XLIFF:doc		    dim fileItr, fileCnt as integer		    dim fileQ as XmlNodeList		    dim fileNode as xmlnode		    fileQ = me.myXLIFFxml.XQL("//file")		    fileCnt = fileQ.Length		    if fileCnt > 0 then		      fileItr = 0		      fileNode = fileQ.item(fileItr)		      fileSrc = fileNode.GetAttribute("source-language")		      fileTgt = fileNode.GetAttribute("target-language")		    end if		    		    // compare. note that we don't care about matching regions here, only base languages		    dim shortFileSrc, shortFileTgt as string		    dim shortGlossSrc, shortGlossTgt as string		    shortFileSrc = getShortLangCodeFromLong(fileSrc)		    shortFileTgt = getShortLangCodeFromLong(fileTgt)		    shortGlossSrc = getShortLangCodeFromLong(glossSrc)		    shortGlossTgt = getShortLangCodeFromLong(glossTgt)		    // any that were returned as "" represent invalid language tags		    // don't worry about reporting fileSrc and fileTgt here, as they will have been reported in checkFile()		    if shortGlossSrc = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("The dx:src-lang attribute for the <dx:utx-glossary> element in this XLIFF:doc appears to have an invalid language code ($1$).",glossSrc),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    if shortGlossTgt = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("The dx:tgt-lang attribute for the <dx:utx-glossary> element in this XLIFF:doc appears to have an invalid language code ($1$).",glossTgt),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // now the actual compare		    if shortFileSrc <> shortGlossSrc then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("The dx:src-lang attribute ($1$) for the <dx:utx-glossary> element in this XLIFF:doc must be a match for at least the base source language code of this XLIFF:doc ($2$).",glossSrc,fileSrc),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    if shortFileTgt <> shortGlossTgt then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("The dx:tgt-lang attribute ($1$) for the <dx:utx-glossary> element in this XLIFF:doc must be a match for at least the base target language code of this XLIFF:doc ($2$).",glossTgt,fileTgt),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    		    // check that dx:version was set		    dim s as string = glossNode.GetAttribute("dx:version")		    if s = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("The <dx:utx-glossary> element in this XLIFF:doc does not have any value set for the dx:version attribute."),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check thatdx:date-created was set		    s = glossNode.GetAttribute("dx:date-created")		    if s = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("The <dx:utx-glossary> element in this XLIFF:doc does not have any value set for the dx:date-created attribute."),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that dx:creator was set		    s = glossNode.GetAttribute("dx:creator")		    if s = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT,localize.getwp("The <dx:utx-glossary> element in this XLIFF:doc does not have any value set for the dx:creator attribute."),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		  next glossItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxUtxSrc()		  '<dx:utx-src>		  'This element maps information related to the source language, from a UTX glossary (column 1). The text contents of the element must consist of the term as represented in the source language.		  'Parent Elements: <dx:utx-term>		  'Child Elements: none		  'Required Attributes: dx:pos		  'dx:pos		  'This is the source part-of-speech from the UTX glossary (column 3). See the UTX standard for more information.		  'Acceptable values: noun, properNoun, verb, adjective, adverb, sentence		  		  // iterate through the <dx:utx-src> objects		  dim srcItr, srcCnt as integer		  dim srcQ as XmlNodeList		  dim srcNode as xmlnode		  srcQ = me.myXLIFFxml.XQL("//dx:utx-glossary/dx:utx-term/dx:utx-src")		  srcCnt = srcQ.Length		  		  for srcItr = 0 to srcCnt - 1		    srcNode = srcQ.item(srcItr)		    		    // check that dx:status is one of the allowed values		    dim definedPoS as string = srcNode.getAttribute("dx:pos")		    if me.allowedUtxSrcPoS.IndexOf(definedPoS) < 0 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_SRC_ELEMENT,localize.getwp("The <dx:utx-src> element for <dx:utx-term> $1$ has an invalid Part Of Speech (dx:pos) value: $2$",srcNode.parent.GetAttribute("dx:entry-id"),definedPoS),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		  next srcItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxUtxTerm()		  '<dx:utx-term>		  'This element has one function: to provide a look-up reference to the embedded UTX glossary.		  '        It must contain 1 <dx:utx-src> element and 1 <dx:utx-tgt> element.		  '        It may optionally have 1 <dx:utx-comment> element.		  // NOTE: will leave the above for an XSD schema validation check.		  'Parent Elements: <dx:utx-glossary>		  'Child Elements: <dx:utx-src>{1,1}, <dx:utx-tgt>{1,1}, <dx:utx-comment>?		  'Required Attributes: dx:entry-id		  'dx:entry-id		  'This is a unique id that will be referenced by every TU that has a hit for this term.		  'Acceptable values: any value that is unique within the XLIFF:doc file.		  'Optional Attributes: dx:concept-id		  'dx:concept-id		  'This is an optional reference to an external glossary. XLIFF:doc does not require a tool to act on this id if provided, by, for example, providing lookup against external terminology sources, such as TBX files included in the TIP, a term server, etc.		  		  // list of termIDs: these must be unique throughout the file		  dim termIDsforUniquenessCheck(-1) as string		  		  // iterate through the <dx:utx-term> objects		  dim termItr, termCnt as integer		  dim termQ as XmlNodeList		  dim termNode as xmlnode		  termQ = me.myXLIFFxml.XQL("//dx:utx-glossary/dx:utx-term")		  termCnt = termQ.Length		  		  for termItr = 0 to termCnt - 1		    termNode = termQ.item(termItr)		    dim thisTermID as string		    thisTermID = termNode.GetAttribute("dx:entry-id")		    termIDsforUniquenessCheck.append thisTermID		  next termItr		  		  // check if all term IDs are unique within the file.		  dim listofNonUniqueIDs(-1) as string		  listofNonUniqueIDs = common.returnDuplicatesFromArray(termIDsforUniquenessCheck)		  if ubound(listofNonUniqueIDs) <> -1 then		    me.errorsEncountered = true		    dim newError as XLIFFdocError		    newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_TERM_ELEMENT,localize.getwp("One or more of the entry IDs for terms in this XLIFF:doc are non-unique ($1$).",join(listofNonUniqueIDs,", ")),ERROR_LEVEL_ERROR)		    me.myErrors.append newError		  end if		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkDxUtxTgt()		  '<dx:utx-tgt>		  'This element maps information related to the target language, from a UTX glossary (column 2). The text contents of the element must consist of the term as represented in the target language.		  'Parent Elements: <dx:utx-term>		  'Child Elements: none		  'Required Attributes: dx:status		  'dx:status		  'This is the status of the target language term, from the UTX glossary (optional column in UTX, not optional in XLIFF:doc). See the UTX standard for more information.		  'Acceptable values: provisional, approved, non-standard, forbidden		  		  // iterate through the <dx:utx-tgt> objects		  dim tgtItr, tgtCnt as integer		  dim tgtQ as XmlNodeList		  dim tgtNode as xmlnode		  tgtQ = me.myXLIFFxml.XQL("//dx:utx-glossary/dx:utx-term/dx:utx-tgt")		  tgtCnt = tgtQ.Length		  		  for tgtItr = 0 to tgtCnt - 1		    tgtNode = tgtQ.item(tgtItr)		    		    // check that dx:status is one of the allowed values		    dim definedState as string = tgtNode.getAttribute("dx:status")		    if me.allowedUtxTgtStates.IndexOf(definedState) < 0 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DX_UTX_TGT_ELEMENT,localize.getwp("The <dx:utx-tgt> element for <dx:utx-term> $1$ has an invalid dx:status value: $2$",tgtNode.parent.GetAttribute("dx:entry-id"),definedState),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		  next tgtItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkFile()		  '<file>                               .		  'Parent Elements: <xliff>		  'Child Elements: <header>{1,1}, <body>{1,1}		  'Required Attributes: original, source-language, datatype, target-language, xml:space, dx:allow-tu-join, dx:allow-tu-split, dx:allow-tm-match-addition, dx:allow-tm-match-deletion, dx:allow-tb-match-addition, dx:allow-tb-match-deletion, dx:allow-qa-addition, dx:allow-qa-deletion		  'xml:space		  // attributes in <file> that are not permitted in XLIFF:doc:		  'tool, tool-id, date, ts, category, product-name, product-version, build-num		  		  		  // list to hold all the source and target languages we find.		  dim srcLangs(-1) as string		  dim tgtLangs(-1) as string		  		  // iterate through the <file> objects		  dim fileItr, fileCnt as integer		  dim fileQ as XmlNodeList		  dim fileNode as xmlnode		  fileQ = me.myXLIFFxml.XQL("//file")		  fileCnt = fileQ.Length		  		  // must be at least 1 file element.		  if fileCnt = 0 then		    me.errorsEncountered = true		    dim newError as XLIFFdocError		    newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("This XLIFF:doc does not have any <file> elements, but it must have at least one."),ERROR_LEVEL_ERROR)		    me.myErrors.append newError		    // no point in continuing, there's nothing to check		    return		  end if		  		  for fileItr = 0 to fileCnt - 1		    fileNode = fileQ.item(fileItr)		    dim originalValue as string = fileNode.GetAttribute("original")		    		    // valid source and target lang?		    dim fileSrc, fileTgt as string		    fileSrc = fileNode.GetAttribute("source-language")		    fileTgt = fileNode.GetAttribute("target-language")		    dim shortFileSrc, shortFileTgt as string		    shortFileSrc = getShortLangCodeFromLong(fileSrc)		    shortFileTgt = getShortLangCodeFromLong(fileTgt)		    // any that were returned as "" represent invalid language tags		    if shortFileSrc = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("The source-language attribute for the <file> element with original=""$2$"" appears to have an invalid language code ($1$).",fileSrc,originalValue),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    if shortFileTgt = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("The target-language attribute for the <file> element with original=""$2$"" appears to have an invalid language code ($1$).",fileTgt,originalValue),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // do all <file> elements have the same source/target languages? build up a list and check later.		    srcLangs.append fileSrc		    tgtLangs.append fileTgt		    		    // check for some required attributes that don't have defaults		    // check that original was set		    if originalValue = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("A <file> element in this XLIFF:doc does not have any value set for the original attribute."),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that datatype was set		    dim s as string		    s = fileNode.GetAttribute("datatype")		    if s = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("The <file> element with original=""$1$"" does not have any value set for the datatype attribute.",originalValue),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    else		      // check that datatype is one of the predefined values, or starts with "x-"		      if me.allowedDataTypes.IndexOf(s) < 0 then		        // user-defined ones starting with "x-" are allowed		        if left(s,2) <> "x-" and len(s) > 2 then		          me.errorsEncountered = true		          dim newError as XLIFFdocError		          newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("The <file> element with original=""$1$"" defines an illegal value ($2$) for the datatype attribute.",originalValue,s),ERROR_LEVEL_ERROR)		          me.myErrors.append newError		        end if		      end if		    end if		    		    // check for some XLIFF 1.2 attributes that are not to be used		    dim illegalAttributes(-1) as string		    illegalAttributes = array("'tool", "tool-id", "date", "ts", "category", "product-name", "product-version", "build-num")		    dim i, cnt as integer		    cnt = ubound(illegalAttributes)		    for i = 0 to cnt		      s = fileNode.GetAttribute(illegalAttributes(i))		      if s <> "" then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("The <file> element with original=""$1$"" defines a value for the $2$ attribute, but that attribute is not permitted in XLIFF:doc.",originalValue,illegalAttributes(i)),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    next i		    		  next fileItr		  		  // now compare all source-language and target-language values we stored, and see if any are different.		  if ubound(srcLangs) > 0 then		    if not common.checkStringArrayContentsAreIdentical(srcLangs) then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("This XLIFF:doc has multiple <file> elements, but the source languages specified in them are not identical."),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    if not common.checkStringArrayContentsAreIdentical(tgtLangs) then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_FILE_ELEMENT,localize.getwp("This XLIFF:doc has multiple <file> elements, but the target languages specified in them are not identical."),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		  end if		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkForDisallowedElements()		  // the following XLIFF 1.2 elements are not allowed in XLIFF:doc		  '<bin-source>		  '<bin-target>		  '<bin-unit>		  '<bpt>		  '<bx/>		  '<context-group>		  '<context>		  '<count-group>		  '<count>		  '<ept>		  '<ex/>		  '<glossary>		  '<internal-file>		  '<it>		  '<note>		  '<ph>		  '<phase-group>		  '<phase>		  '<prop-group>		  '<prop>		  '<reference>		  '<seg-source>		  '<sub>		  		  dim namesForErrorReport(-1) as string		  namesForErrorReport = array( _		  "<bin-source>","<bin-target>","<bin-unit>","<bpt>","<bx/>","<context-group>","<context>","<count-group>",_		  "<count>","<ept>","<ex/>","<glossary>","<internal-file>","<it>","<note>","<ph>","<phase-group>","<phase>",_		  "<prop-group>","<prop>","<reference>","<seg-source>","<sub>")		  dim illegalElementNames(-1) as string		  illegalElementNames = array( _		  "//bin-source","//bin-target","//bin-unit","//bpt","//bx","//context-group","//context","//count-group",_		  "//count","//ept","//ex","//glossary","//internal-file","//it","//note","//ph","//phase-group","//phase",_		  "//prop-group","//prop","//reference","//seg-source","//sub")		  		  // check for presence of any of the elements. any hit produces an error.		  dim i,cnt as integer		  cnt = ubound(illegalElementNames)		  for i = 0 to cnt		    dim badElementQ as XmlNodeList		    badElementQ = me.myXLIFFxml.XQL(illegalElementNames(i))		    if badElementQ.Length > 0 then		      // should not be any of these elements present, but there is at least one.		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_DISALLOWED_ELEMENTS,namesForErrorReport(i),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		  next i		  		  return		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Function CheckForNonNegativeIntegerIDs(theID as String) As boolean		  // checks if the value passed is a non-negative integer value.		  // returns true if so.		  		  if round(abs(val(theID))) <> val(theID) then		    // this should mean that the string ID was either not an integer, or that it was negative.		    return false		  else		    return true		  end if		  		  		End Function	#tag EndMethod	#tag Method, Flags = &h0		Sub checkG()		  'dx:orig-markup-open		  'dx:orig-markup-close		  'If the original markup can be escaped safely and included, put it into this attribute. If the original markup cannot be safely encoded in XML, do not include this attribute.		  'dx:equiv-markup-open		  'dx:equiv-markup-close		  'HTML code that approximates the formatting of the original document format. For example, if the original markup was a a font change that made the text italicized, the dx:equiv-markup-open might be "&lt;i&gt;" and the dx:equiv-markup-close might be "&lt;/i&gt;"		  'Note: if the original format is HTML, and the HTML formatting can be represented safely, it is not necessary to include dx:equiv-markup attributes. If not present, the dx:orig-markup will be used.		  		  // iterate through the <trans-unit> objects		  dim tuItr, tuCnt as integer		  dim tuQ as XmlNodeList		  dim theTuNode as xmlnode		  dim tuID as string		  tuQ = me.myXLIFFxml.XQL("//trans-unit")		  tuCnt = tuQ.Length		  		  for tuItr = 0 to tuCnt - 1		    theTuNode = tuQ.item(tuItr)		    tuid = theTuNode.GetAttribute("id")		    		    // any <g>s to worry about?		    dim gCnt as integer		    dim gQ as XmlNodeList		    gQ = theTuNode.XQL("source/g|source/mrk/g|target/g|target/mrk/g")		    gCnt = gQ.length		    if gCnt < 1 then		      // no g's, go on to next TU		      continue for tuItr		    end if		    		    // check attributes are present and populated correctly for each <g> node		    dim i as integer		    for i = 0 to gCnt - 1		      dim theGnode as xmlnode		      dim gID as string		      theGnode = gQ.item(i)		      gID = theGnode.getattribute("id")		      // get to whether this was source or target for better reporting		      dim srcTgtElementName as string		      srcTgtElementName = getSrcOrTgtforXorG(theGnode)		      		      // ctype		      dim theCType as string		      theCType = theGnode.GetAttribute("ctype")		      if theCType = "" then		        // error. Must be defined.		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_G_ELEMENT,localize.getwp(_		        "ctype attribute not defined for <g> element $1$ in the $3$ of <trans-unit> $2$",gID,tuID,srcTgtElementName),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      else		        // defined. check if it is one of the allowed values		        if me.allowedCtypesForG.IndexOf(theCType) = -1 then		          // defined value is not permitted		          me.errorsEncountered = true		          dim newError as XLIFFdocError		          newError = new XLIFFdocError(ERROR_CATEGORY_G_ELEMENT,localize.getwp(_		          "ctype attribute value ""$3$"" for <g> element $1$ in the $4$ of <trans-unit> $2$ is not a permitted value.",gID,tuID,theCType,srcTgtElementName),ERROR_LEVEL_ERROR)		          me.myErrors.append newError		        end if		      end if		      		      // dx:equiv-markup-open and dx:equiv-markup-close		      // we will use this rule here: if dx:equiv-markup is not defined, and dx:orig-markup is also not defined or doesn't start with a "<", then we'll flag this is a probable error.		      dim checkWhatEquiv(-1) as string		      checkWhatEquiv = array("dx:equiv-markup-open","dx:equiv-markup-close")		      dim checkWhatOrig(-1) as string		      checkWhatOrig = array("dx:orig-markup-open","dx:orig-markup-close")		      dim equivMarkup, origMarkup as string		      dim j as integer		      for j = 0 to 1		        equivMarkup = theGnode.GetAttribute(checkWhatEquiv(j))		        // if equivMarkup is present, we're good, so check that first...		        if equivMarkup = "" then		          origMarkup = theGnode.GetAttribute(checkWhatOrig(j))		          if origMarkup = "" then		            me.errorsEncountered = true		            dim newError as XLIFFdocError		            newError = new XLIFFdocError(ERROR_CATEGORY_G_ELEMENT,localize.getwp(_		            "$4$ attribute value for <g> element $1$ in the $3$ of <trans-unit> $2$ was not defined, but must be defined if dx:orig-markup-open does not contain HTML markup (dx:orig-markup-open not defined here).",gID,tuID,srcTgtElementName,checkWhatOrig(j)),ERROR_LEVEL_ERROR)		            me.myErrors.append newError		          else		            // more complex check: compare dx:orig-markup against known HTML (4.0) elements.		            if not checkGXequivMarkup(origMarkup) then		              me.errorsEncountered = true		              dim newError as XLIFFdocError		              newError = new XLIFFdocError(ERROR_CATEGORY_G_ELEMENT,localize.getwp(_		              "$4$ attribute value for <g> element $1$ in the $3$ of <trans-unit> $2$ was not defined, but must be defined if dx:orig-markup-open does not contain HTML markup (dx:orig-markup-open appears to contain something other than HTML markup).",gID,tuID,srcTgtElementName,checkWhatOrig(j)),ERROR_LEVEL_WARNING)		              me.myErrors.append newError		            end if		          end if		        end if		      next j		    next i		  next tuItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkGroup()		  // In XLIFF:doc, the <group> element is used only to prevent specific TUs from being joined.		  // The <body> element needs at least 1 <group> element, and all TUs have to be part of a <group>.		  // The id must be unique within the <file>, but it ids can be recycled from file to file.		  		  		  		  // iterate through the <file> objects		  dim bodyItr, bodyCnt as integer		  dim bodyQ as XmlNodeList		  dim thebodyNode as xmlnode		  bodyQ = me.myXLIFFxml.XQL("//file/body")		  bodyCnt = bodyQ.Length		  		  for bodyItr = 0 to bodyCnt - 1		    thebodyNode = bodyQ.item(bodyItr)		    		    // any nested <groups> in this file?		    dim doubleGroupQ as XmlNodeList		    doubleGroupQ = thebodyNode.XQL("group/group")		    if doubleGroupQ.length > 0 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_GROUP_ELEMENT,localize.getwp("There are nested <group> elements within this file: $1$",thebodyNode.parent.GetAttribute("original")),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		      // rather than returning here, might as well let other checks continue...		    end if		    		    // is there at least one <group> element for each file/body element?		    dim groupCnt as integer		    dim groupQ as XmlNodeList		    groupQ = thebodyNode.XQL("group")		    groupCnt = groupQ.length		    if groupCnt < 1 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_GROUP_ELEMENT,localize.getwp("The <body> element in this file element does not have any <group> elements: $1$",thebodyNode.parent.GetAttribute("original")),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		      // rather than returning here, might as well let other checks continue...		    end if		    		    // get ids of ids listed in the <group> nodes		    dim groupIDs(-1) as string		    if groupCnt > 0 then		      dim i as integer		      for i = 0 to groupCnt - 1		        groupIDs.append groupQ.item(i).getattribute("id")		      next i		      // check if the group IDs are all unique within themselves.		      dim listofNonUniqueIDs(-1) as string		      listofNonUniqueIDs = common.returnDuplicatesFromArray(groupIDs)		      if ubound(listofNonUniqueIDs) <> -1 then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_GROUP_ELEMENT,localize.getwp("One or more of the <group> ids in this file element are non-unique: $1$ ($2$)",thebodyNode.parent.GetAttribute("original"),join(listofNonUniqueIDs,", ")),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		        // rather than returning here, might as well let other checks continue...		      end if		    end if		    		  next bodyItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Function checkGXequivMarkup(origMarkup as String) As boolean		  // returns true if origMarkup appears to contain HTML. Returns false conservatively.		  		  if left(origMarkup,1) <> "<" then		    return false		  else		    dim origMarkupFirstTagName as string		    Dim rg as New RegEx		    Dim myMatch as RegExMatch		    rg.SearchPattern="<\/?(\w+)[\s\/\>]"		    // find first match. as long as first tag is HTML, we'll assume rest is ok too.		    myMatch=rg.search(origMarkup)		    if myMatch <> Nil then		      if myMatch.SubExpressionCount > 1 then		        origMarkupFirstTagName = myMatch.SubExpressionString(1)		        // compare to list of HTML 4.0 tags		        if me.allowedHTMLtags.IndexOf(origMarkupFirstTagName) < 0 then		          return false		        end if		      else		        // a hit for the pattern as a whole, but not on the tag name		        return false		      end if		    else		      // no hit = no HTML tag probably		      return false		    End if		  end if		  		End Function	#tag EndMethod	#tag Method, Flags = &h0		Sub checkMrk()		  '<mrk>		  'This element has one function in XLIFF:doc: to provide a look-up reference to the embedded UTX glossary. This element is placed around a piece of text identified as being a term in the glossary. It can be used to demarcate terms in both the source and target.		  'Parent Elements: <source>, <target>		  'Child Elements: <g>*, <x>*		  'Required Attributes: mtype, dx:term-id		  'mtype		  'The value for this attribute in XLIFF:doc must be "term".		  'dx:term-id		  'Reference to the entry-id attribute of the <dx:utx-term> that contains a term designated as a match or hit for this element's grand-parent <trans-unit>.		  		  		  // iterate through the <mrk> objects		  dim mrkItr, mrkCnt as integer		  dim mrkQ as XmlNodeList		  dim mrkNode as xmlnode		  mrkQ = me.myXLIFFxml.XQL("//mrk")		  mrkCnt = mrkQ.Length		  		  for mrkItr = 0 to mrkCnt - 1		    mrkNode = mrkQ.item(mrkItr)		    		    dim ancestorTUnode as xmlnode		    ancestorTUnode = getAncestorTransUnit(mrkNode)		    dim tuid as string		    if ancestorTUnode <> nil then		      tuid = ancestorTUnode.GetAttribute("id")		    end if		    		    // is mtype set correctly?		    if mrkNode.GetAttribute("mtype") <> "term" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_MRK_ELEMENT,localize.getwp("A <mrk> element in <trans-unit> $1$ does not have ""term"" set for the mtype attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // does it have at least one thing it is surrounding? it must mark off something.		    dim i, cnt as integer		    dim hasTextChild as boolean = false		    cnt = mrkNode.ChildCount - 1		    for i = 0 to cnt		      if mrkNode.child(i) isa XmlTextNode then		        hasTextChild = true		        exit for i		      end if		    next i		    if not hasTextChild then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_MRK_ELEMENT,localize.getwp("A <mrk> element in <trans-unit> $1$ does not encapsulate any text nodes. The <mrk> element must highlight at least 1 character of text.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		    // check that dx:term-id was set		    dim givenID as string =mrkNode.GetAttribute("dx:term-id")		    if givenID = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_MRK_ELEMENT,localize.getwp("A <mrk> element in <trans-unit> $1$ does not have any value set for the dx:term-id attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    else		      // check that dx:term-id actually matches against something.		      dim termQ as XmlNodeList		      termQ = me.myXLIFFxml.XQL("//dx:utx-glossary/dx:utx-term[@dx:entry-id='" + givenID + "']")		      if termQ.Length < 1 then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_MRK_ELEMENT,localize.getwp("A <mrk> element in <trans-unit> $1$ has a dx:term-id attribute ($2$) that does not match anything in the embedded glossary.",tuid,givenID),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    end if		    		  next mrkItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkTarget()		  // In XLIFF:doc, the <target> element must specify a "state" attribute. or leave empty, whence it will be assumed to be "new".		  'Acceptable values: "new", "translated", "final", "signed-off", "needs-review-translation". Default value: "new".		  		  // iterate through the <target> objects		  dim tgtItr, tgtCnt as integer		  dim tgtQ as XmlNodeList		  dim theTgtNode as xmlnode		  tgtQ = me.myXLIFFxml.XQL("//target")		  tgtCnt = tgtQ.Length		  		  for tgtItr = 0 to tgtCnt - 1		    theTgtNode = tgtQ.item(tgtItr)		    		    dim definedState as string = theTgtNode.getAttribute("state")		    if definedState <> "" then		      if me.allowedTargetStates.IndexOf(definedState) < 0 then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_TARGET_ELEMENT,localize.getwp("The <target> element for <trans-unit> $1$ has an invalid state value: $2$",theTgtNode.parent.GetAttribute("id"),definedState),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    else		      // so, the default state if none is set, is "new". but should an alt-trans with revision history have NO state at all? probably not. better do a warning.		      if theTgtNode.parent.LocalName = "alt-trans" and theTgtNode.parent.GetAttribute("alttranstype") = "previous-version" then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_TARGET_ELEMENT,localize.getwp("The <target> element for an <alt-trans> revision history element in <trans-unit> $1$ has no state value, but the default value of ""new"" is probably not appropriate for a revision history item.",theTgtNode.parent.parent.GetAttribute("id")),ERROR_LEVEL_WARNING)		        me.myErrors.append newError		      end if		    end if		  next tgtItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkTransUnit()		  'Required Attributes: id, dx:match-quality, dx:glorious-match, dx:repetition, dx:match-penalty, dx:origin, dx:origin-shorttext, dx:modified-by, dx:modified-at		  'id		  'Acceptable values: any value that is unique within the XLIFF:doc file.		  'dx:match-quality		  'Use values 0-100. The use of decimal numbers is acceptable, but only a single digit of precision is allowed. For example, "99.5" is acceptable, but "99.52" is not. Do not use a percent sign. Higher numbers refer to better matches than lower numbers.		  'Remove this attribute if the user manually edits the <target> after the match was placed.		  'Note: this mimics the match-quality attribute of <alt-trans> in XLIFF 1.2, giving us the same functionality for the <trans-unit> element.		  'dx:glorious-match		  'Indicates whether the match is an exact, in-context match (as determined by the tool that generated the match). Remove this attribute if the user manually edits the <target> after the match was placed. Acceptable values: "yes", "no". Default value: "no".		  'dx:repetition		  'Indicates whether this translation unit has been classified as a repetition (same exact source as other translations in the same project). XLIFF:doc does not specify how to determine if a TU is a repetition or not (2 occurrences vs 3, etc.). XLIFF:doc does not distinguish between first instance of a repetition and subsequent instances. Acceptable values: "yes", "no". Default value: "no".		  'dx:origin		  'Acceptable values: "TM", "MT", "XLIFF", "manual", “sourcetext”, “pseudo-trans”. If the match was pulled from the <alt-trans> in the XLIFF:doc doc, this value must match the origin value of the <alt-trans> match.		  'dx:origin-shorttext		  'Human-readable string describing the match origin. This could be the name of the TM it came out of, the name of an MT engine, etc. Examples: "Master TM 1", "Google MT", "myDocument.docx.xlf", "Manual Translation". Exact values are not defined by XLIFF:doc.		  'dx:match-penalty		  'Identifies what, if any, artificial (non-textual) penalty was applied to the match by the tool that generated the match. Use values 0-100. The use of decimal numbers is acceptable, but only a single digit of precision is allowed. For example, "0.5" is acceptable, but "0.48" is not. Do not use a percent sign. Higher numbers refer to larger penalties than lower numbers.		  'Remove this attribute if the user manually edits the <target> after the match was placed.		  'dx:modified-by		  'String value identifying the user (human or automatic) responsible for the most recent modification. Modification could include changing an attribute of the <trans-unit> element, or any change to the <target> element.		  'dx:modified-at		  'Time and date the <trans-unit> was last modified. This can represent the date/time the translation was edited, or when a TM match was applied, or when the <trans-unit> was processed in some other way.		  'Note: Date/time must be specified in ISO 8601 format. Time must be specified in UTC (Zulu) time zone. See the XLIFF date element for more information.		  		  // iterate through the <trans-unit> objects		  dim tuItr, tuCnt as integer		  dim tuQ as XmlNodeList		  dim tuNode as xmlnode		  tuQ = me.myXLIFFxml.XQL("//trans-unit")		  tuCnt = tuQ.Length		  		  for tuItr = 0 to tuCnt - 1		    tuNode = tuQ.item(tuItr)		    		    // get tuid for easier reporting		    dim tuid as string		    tuid = "<trans-unit> " + tuNode.GetAttribute("id")		    		    // get reference to target child, in case we need it later		    dim targetNode as xmlNode		    targetNode = tuNode.getFirstChildByName("target")		    		    // check that dx:match-penalty and match-quality have single-digit precision numbers in range 0 - 100		    dim matchRateTypes(1) as string = array("dx:match-quality","dx:match-penalty")		    dim i as integer		    for i = 0 to 1		      dim thisValue as string		      thisValue = tuNode.GetAttribute(matchRateTypes(i))		      dim valAsInteger as integer		      valAsInteger = val(thisValue) * 10		      if valAsInteger <> val(thisValue) * 10 then		        // proves the number has more than single digit precision		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("$1$ has a $2$ attribute with greater than single-digit precision ($3$).",tuid,matchRateTypes(i),thisValue),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		      if valAsInteger < 0 or valAsInteger > 1000 then		        // outside of range of 0.0 to 100.0		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("$1$ has a $2$ attribute outside of the range of 0.0 to 100.0 ($3$).",tuid,matchRateTypes(i),thisValue),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    next i		    		    // check origin against pre-defined allowed values		    dim definedMatchOrigin as string = tuNode.getAttribute("dx:origin")		    if definedMatchOrigin <> "" then		      if me.allowedMatchOrigins.IndexOf(definedMatchOrigin) < 0 then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("$1$ has an invalid dx:origin value: $2$",tuid,definedMatchOrigin),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    else		      // doesn't have one, but MUST, unless there is no target		      if targetNode <> nil and targetNode.ChildCount > 0 then		        // has a target, so it needed to have some origin value.		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("$1$ has no dx:origin value set.",tuid),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    end if		    // check that dx:origin-shorttext was set		    if tuNode.GetAttribute("dx:origin-shorttext") = "" then		      if targetNode <> nil and targetNode.ChildCount > 0 then		        // has a target, so it needed to have some origin value.		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("$1$ does not have any value set for the dx:origin-shorttext attribute.",tuid),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    end if		    // check that dx:modified-at was set		    if tuNode.GetAttribute("dx:modified-at") = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("$1$ does not have any value set for the dx:modified-at attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    // check that dx:modified-at was set		    if tuNode.GetAttribute("dx:modified-by") = "" then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_TU_ELEMENT,localize.getwp("$1$ does not have any value set for the dx:modified-by attribute.",tuid),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		    end if		    		  next tuItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkX()		  'dx:orig-markup		  'If the original markup can be escaped safely and included, put it into this attribute. If the original markup cannot be safely encoded in XML, do not include this attribute.		  'dx:equiv-markup		  'HTML code that approximates the formatting of the original document format. For example, if the original markup was a line break, the dx:equiv-markup might be "<br>".		  'Note: if the original format is HTML, and the HTML formatting can be represented safely, it is not necessary to include dx:equiv-markup attributes.		  'If not present, the dx:orig-markup will be used.		  		  // iterate through the <trans-unit> objects		  dim tuItr, tuCnt as integer		  dim tuQ as XmlNodeList		  dim theTuNode as xmlnode		  dim tuID as string		  tuQ = me.myXLIFFxml.XQL("//trans-unit")		  tuCnt = tuQ.Length		  		  for tuItr = 0 to tuCnt - 1		    theTuNode = tuQ.item(tuItr)		    tuid = theTuNode.GetAttribute("id")		    		    // any <x>s to worry about?		    dim xCnt as integer		    dim xQ as XmlNodeList		    xQ = theTuNode.XQL("source/x|source/g/x|source/mrk/x|source/mrk/g/x|target/x|target/g/x|target/mrk/x|target/mrk/g/x")		    xCnt = xQ.length		    if xCnt < 1 then		      // no x's, go on to next TU		      continue for tuItr		    end if		    		    // check attributes are present and populated correctly for each <x> node		    dim i as integer		    for i = 0 to xCnt - 1		      dim theXnode as xmlnode		      dim xID as string		      theXNode = xQ.item(i)		      xID = theXNode.getattribute("id")		      // get to whether this was source or target for better reporting		      dim srcTgtElementName as string		      srcTgtElementName = getSrcOrTgtforXorG(theXnode)		      'if theXnode.parent.LocalName <> "g" then		      'srcTgtElementName = "<"+ theXnode.parent.LocalName + ">"		      'elseif theXnode.parent.localName <> "mrk" then		      'srcTgtElementName = "<"+ theXnode.parent.LocalName + ">"		      'else		      'srcTgtElementName = "<"+ theXnode.parent.parent.LocalName + ">"		      'end if		      		      // ctype		      dim theCType as string		      theCType = theXnode.GetAttribute("ctype")		      if theCType = "" then		        // error. Must be defined.		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_X_ELEMENT,localize.getwp(_		        "ctype attribute not defined for <x> element $1$ in the $3$ of <trans-unit> $2$",xID,tuID,srcTgtElementName))		        me.myErrors.append newError		      else		        // defined. check if it is one of the allowed values		        if me.allowedCtypesForX.IndexOf(theCType) = -1 then		          // defined value is not permitted		          me.errorsEncountered = true		          dim newError as XLIFFdocError		          newError = new XLIFFdocError(ERROR_CATEGORY_X_ELEMENT,localize.getwp(_		          "ctype attribute value ""$3$"" for <x> element $1$ in the $4$ of <trans-unit> $2$ is not a permitted value.",xID,tuID,theCType,srcTgtElementName),ERROR_LEVEL_ERROR)		          me.myErrors.append newError		        end if		      end if		      		      // dx:equiv-markup		      // we will use this rule here: if dx:equiv-markup is not defined, and dx:orig-markup is also not defined or doesn't start with a "<", then we'll flag this is a probable error.		      dim equivMarkup, origMarkup as string		      equivMarkup = theXnode.GetAttribute("dx:equiv-markup")		      origMarkup = theXnode.GetAttribute("dx:orig-markup")		      if equivMarkup = "" then		        if origMarkup = "" then		          me.errorsEncountered = true		          dim newError as XLIFFdocError		          newError = new XLIFFdocError(ERROR_CATEGORY_X_ELEMENT,localize.getwp(_		          "dx:equiv-markup attribute value for <x> element $1$ in the $3$ of <trans-unit> $2$ was not defined, but must be defined if dx:orig-markup does not contain HTML markup (dx:orig-markup not defined here).",xID,tuID,srcTgtElementName),ERROR_LEVEL_ERROR)		          me.myErrors.append newError		        else		          // more complex check: compare dx:orig-markup against known HTML (4.0) elements.		          if not checkGXequivMarkup(origMarkup) then		            me.errorsEncountered = true		            dim newError as XLIFFdocError		            newError = new XLIFFdocError(ERROR_CATEGORY_X_ELEMENT,localize.getwp(_		            "dx:equiv-markup attribute value for <x> element $1$ in the $3$ of <trans-unit> $2$ was not defined, but must be defined if dx:orig-markup does not contain HTML markup (dx:orig-markup appears to contain something other than HTML markup).",xID,tuID,srcTgtElementName),ERROR_LEVEL_WARNING)		            me.myErrors.append newError		          end if		        end if		      end if		      		    next i		    		  next tuItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Sub checkXandGforUniqueIDs()		  // in XLIFF:doc, <g> and <x> must not re-use IDs between them, within a single TU.		  // this method gets all <g> and <x> ids for a TU, and checks for duplicates.		  'id		  'The id is the primary mechanism for matching placeholders from source to target.		  'The id must be unique within the <trans-unit>, but it ids can be recycled from trans-unit to trans-unit.		  'An id used for a <g> element cannot be re-used for an <x> element within the same <trans-unit>.		  'Acceptable values: non-negative integers		  		  // iterate through the <trans-unit> objects		  dim tuItr, tuCnt as integer		  dim tuQ as XmlNodeList		  dim theSrcTgtNode as xmlnode		  dim tuID as string		  tuQ = me.myXLIFFxml.XQL("//trans-unit/source|//trans-unit/target")		  tuCnt = tuQ.Length		  		  for tuItr = 0 to tuCnt - 1		    theSrcTgtNode = tuQ.item(tuItr)		    tuid = theSrcTgtNode.Parent.GetAttribute("id")		    dim srcTgtElementName as string		    srcTgtElementName = "<"+ theSrcTgtNode.LocalName + ">"		    		    // any <x>s or <g>s to worry about?		    // xs can be under source/target or under g. could also be under mrk.		    dim thisTUsPlaceholders(-1) as xmlnode		    dim xgCnt as integer		    dim xgQ as XmlNodeList		    dim i as integer		    xgQ = theSrcTgtNode.XQL("x|g/x|g|mrk/g|mrk/x")		    xgCnt = xgQ.length		    for i = 0 to xgCnt - 1		      thisTUsPlaceholders.append xgQ.item(i)		    next i		    		    dim placeholderCnt as integer = ubound(thisTUsPlaceholders)		    if placeholderCnt = -1 then		      // no x's or g's, go on to next TU		      continue for tuItr		    end if		    		    // get ids of ids listed in the <x> and <g> nodes		    dim xgIDs(-1) as string		    dim theID as string		    for i = 0 to placeholderCnt		      dim theXGnode as xmlnode		      theXGNode = thisTUsPlaceholders(i)		      theID = theXGNode.getattribute("id")		      xgIDs.append theID		      // check for non-negative integer values		      if not CheckForNonNegativeIntegerIDs(theID) then		        me.errorsEncountered = true		        dim newError as XLIFFdocError		        newError = new XLIFFdocError(ERROR_CATEGORY_X_ELEMENT,localize.getwp(_		        "The id attribute value for <x> or <g> element $1$ in the $3$ of <trans-unit> $2$ does not appear to be a non-negative integer value.",theID,tuID,srcTgtElementName),ERROR_LEVEL_ERROR)		        me.myErrors.append newError		      end if		    next i		    // check if the x/g IDs are all unique within themselves.		    dim listofNonUniqueIDs(-1) as string		    listofNonUniqueIDs = common.returnDuplicatesFromArray(xgIDs)		    if ubound(listofNonUniqueIDs) <> -1 then		      me.errorsEncountered = true		      dim newError as XLIFFdocError		      newError = new XLIFFdocError(ERROR_CATEGORY_PLACEHOLDER_ELEMENTS,localize.getwp(_		      "One or more of the <g> and/or <x> ids in the $3$ of <trans-unit> $1$ are non-unique:  ($2$)",tuid,join(listofNonUniqueIDs,", "),srcTgtElementName),ERROR_LEVEL_ERROR)		      me.myErrors.append newError		      // rather than returning here, might as well let other checks continue...		    end if		  next tuItr		  		  return		  		  		  		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Function checkXLIFFdocVersion() As Integer		  // check this is an XLIFF:doc file, and if so, return the XLIFF:doc version number.		  // return -1 if not an XLIFF:doc file		  		  dim xliffQ as XmlNodeList		  dim xliffNode as XmlNode		  xliffQ = me.myXLIFFxml.XQL("//xliff")		  if xliffQ.length <> 0 then		    xliffNode = xliffQ.item(0)		    		    // is this an XLIFF:doc format XLIFF?		    // we will take presence of dx namespace in <xliff> node as evidence this is supposed to be an XLIFF:doc file.		    if  xliffNode.getAttribute("xmlns:dx") <> "" then		      return val(xliffNode.GetAttribute("dx:version"))		    end if		  end if		  		  // still here? wasn't xliff:doc file.		  return -1		  		End Function	#tag EndMethod	#tag Method, Flags = &h0		Sub Constructor(theXLIFFxml as XmlDocument)		  me.myXLIFFxml = theXLIFFxml		  // build list of allowed ctype values for the <x> and <g> placeholders.		  me.allowedCtypesForX = array("image","pb","lb","x-xref","x-tab","x-other")		  me.allowedCtypesForG = array("bold","italic","underlined","link","x-superscript","x-subscript","x-fixed","x-font","x-fontsize","x-header","x-title","x-other-format","x-other")		  // build list of HTML (4.0) tags to check dx:orig-markup against)		  me.allowedHTMLtags = array(_		  "A","ABBR","ACRONYM","APPLET","AREA","B","BASE","BASEFONT","BDO","BIG","BLOCKQUOTE","BODY",_		  "BR","BUTTON","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","DD","DEL","DFN","DIR","DIV",_		  "DL","DT","EM","FIELDSET","FONT","FORM","FRAME","FRAMESET","H1","H2","H3","H4","H5","H6","HEAD",_		  "HR","HTML","I","IFRAME","IMG","INPUT","INS","ISINDEX","KBD","LABEL","LEGEND","LI","LINK","MAP","MENU",_		  "META","NOFRAMES","NOSCRIPT","OBJECT","OL","OPTGROUP","OPTION","P","PARAM","PRE","Q","S","SAMP",_		  "SCRIPT","SELECT","SMALL","SPAN","STRIKE","STRONG","STYLE","SUB","SUP","TABLE","TD","TEXTAREA",_		  "TFOOT","TH","THEAD","TITLE","TR","TT","U","UL","VAR")		  // build list of allowed target states		  me.allowedTargetStates = array( STATE_NEW, STATE_TRANSLATED, STATE_BACKCHECK_COMPLETE, STATE_VALIDATED, STATE_REJECTED)		  // build list of allowed annotates attribute values used by dx:note		  me.allowedAnnotateValuesForDxNote = array( "source","target","general" )		  // build list of allowed datatypes		  me.allowedDataTypes = array( "asp","c","cdf","cfm","cpp","csharp","cstring","csv","database","documentfooter", _		  "documentheader","filedialog","form","html","htmlbody","ini","interleaf","javaclass","javapropertyresourcebundle",_		  "javalistresourcebundle","javascript","jscript","layout","lisp","margin","menufile","messagefile","mif","mimetype",_		  "mo","msglib","pagefooter","pageheader","parameters","pascal","php","plaintext","po","report","resources","resx",_		  "rtf","sgml","sgmldtd","svg","vbscript","warning","winres","xhtml","xml","xmldtd","xsl","xul" )		  me.allowedUtxTgtStates = array( "provisional", "approved", "non-standard", "forbidden" )		  me.allowedUtxSrcPoS = array( "noun", "properNoun", "verb", "adjective", "adverb", "sentence" )		  me.allowedMatchOrigins = array( "TM", "MT", "XLIFF", "manual", "sourcetext", "pseudo-trans" )		  me.allowedQAcategories = array( "date","inconsistency","internationalization","number","omission","other","pattern","punctuation","tags","terminology","time" )		  me.allowedQaLevels = array( "error", "warning", "non-error" )		  me.allowedQaOrigins = array( "source", "target", "both" )		  		End Sub	#tag EndMethod	#tag Method, Flags = &h0		Function getAncestorTransUnit(theNode as XmlNode) As xmlnode		  // traverses up the xml chain from the passed xml node, stops whenever it gets to <trans-unit>		  		  dim s as string		  while theNode.parent <> nil		    s = theNode.parent.LocalName		    if s = "trans-unit" then		      return theNode.parent		    else		      theNode = theNode.parent		    end if		  wend		  		  // if still here, something was wrong with the original node passed.		  return nil		  		End Function	#tag EndMethod	#tag Method, Flags = &h0		Function getErrorSummary() As string		  // iterate through all errors and return a string containing 1 error per line.		  // stop at an arbitrary number if we have found too many errors (like 3 million, for example, as being too big to report).		  		  dim cutoffMessage as string		  dim i,cnt,max as integer		  max = 10000		  cnt = ubound(me.myErrors)		  if cnt > max then		    cutoffMessage = "... And " + str(cnt-max) + " other errors."		    cnt = max		  end if		  		  dim s as string		  for i = 0 to cnt		    s = s + me.myErrors(i).toString + endofline		  next i		  		  s = s + cutoffMessage		  		  return s		  		End Function	#tag EndMethod	#tag Method, Flags = &h0		Function getShortLangCodeFromLong(s as String) As String		  // Passed a language code which could be ISO 639-2 or ISO639-3, possibly with a region extension, it returns the first 2 or 3 chars as appropriate		  		  // first just check if this is a 2 or 3 char code already. if so, just return it.		  if len(s) < 4 and len(s) > 1 then		    return s		  end if		  		  // find hyphen Separator		  // ref: RFC 5646		  // http://tools.ietf.org/html/rfc5646#section-2.2.2		  'A language tag is composed from a sequence of one or more "subtags",		  'each of which refines or narrows the range of language identified by		  'the overall tag.  Subtags, in turn, are a sequence of alphanumeric		  'characters (letters and digits), distinguished and separated from		  'other subtags in a tag by a hyphen ("-", [Unicode] U+002D).		  		  dim dashpos as integer		  dashpos = instr(s,"-")		  if dashpos = 0 then		    // uh-oh! it's longer than 3 chars, but doesn't have acceptable lang/region divider.		    return ""		  elseif dashpos > 1 and dashpos < 4 then		    return left(s,dashpos-1)		  else		    // something not right about this lang code. make it fail.		    return ""		  end if		  		  		End Function	#tag EndMethod	#tag Method, Flags = &h0		Function getSrcOrTgtforXorG(theNode as XmlNode) As string		  // traverses up the xml chain from the passed xml node, stops whenever it gets to <source> or <target>		  // needed because x and g can be down 2-3 levels from their <source> if they get nested in <g> or <mrk>		  		  dim s as string		  while s = "" and theNode.parent <> nil		    s = theNode.parent.LocalName		    if s = "target" or s = "source" then		      return s		    else		      s = ""		      theNode = theNode.parent		    end if		  wend		  		  // if still here, something was wrong with the original node passed. A g or x MUST be the descendant of either a source or target.		  return "[unknown]"		  		End Function	#tag EndMethod	#tag Method, Flags = &h0		Function validate() As boolean		  // starting place for validation checks.		  // note: no real attempt is made to check anything that would be shown by an XSD validation check.		  		  // check that this is even an XLIFFdoc file		  dim XLIFFdocVersion as integer		  XLIFFdocVersion = checkXLIFFdocVersion		  		  // XLIFF:doc 1.0 elements that we will not try to check here:		  '<body>		  '<external-file>		  '<header>		  '<skl>		  '<source>		  '<tool>		  '<xliff>		  '<dx:attribute>		  '<dx:attributes>		  '<dx:utx-comment>		  '<dx:qa-hits>		  		  		  // perform check against what version of XLIFF:doc?		  select case XLIFFdocVersion		  case 1.0		    // we know about this version, perform appropriate checks		    		    // check for internal preview HTML		    checkDXInternalPreview()		    		    // check <group> elements		    checkGroup()		    		    // check for XLIFF 1.2 elements that are not allowed in XLIFF:doc		    checkForDisallowedElements()		    		    // check <file>		    checkFile()		    		    // check <dx:utx-glossary>		    checkDxUtxGlossary()		    		    // check <dx:utx-term>		    checkDxUtxTerm()		    		    // check <dx:utx-src>		    checkDxUtxSrc()		    		    // check <dx:utx-tgt>		    checkDxUtxTgt()		    		    // check <dx:qa-hit>		    checkDxQaHit()		    		    // check <dx:note> elements		    checkDxNote()		    		    // check target (check correct state values used)		    checkTarget()		    		    // check <mrk>		    checkMrk()		    		    // check for non-unique <x> and <g> ids, and other issues with the ID numbers.		    checkXandGforUniqueIDs()		    		    // check for proper <x> attributes		    checkX()		    		    // check for proper <g> attributes		    checkG()		    		    // check textual context (dx:context/etc)		    checkDxContext()		    		    // check alt-trans		    checkAltTrans()		    		    // check trans-units		    checkTransUnit()		    		    // all done		    return not me.errorsEncountered		    		  case -1		    // this would be the result if it didn't appear this was an XLIFF:doc file.		    dim theError as new XLIFFdocError(ERROR_CATEGORY_VERSION,localize.getwp("This does not appear to be an XLIFF:doc file."))		    me.myErrors.append theError		    me.errorsEncountered = true		    return false		  case else		    // we don't know how to validate other versions of XLIFF:doc		    dim theError as new XLIFFdocError(ERROR_CATEGORY_VERSION,localize.getwp("Unknown XLIFF:doc version: $1$",str(XLIFFdocVersion)))		    me.myErrors.append theError		    me.errorsEncountered = true		    return false		  end select		  		  		End Function	#tag EndMethod	#tag Property, Flags = &h0		allowedAnnotateValuesForDxNote() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedCtypesForG() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedCtypesForX() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedDataTypes() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedHTMLtags() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedMatchOrigins() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedQAcategories() As String	#tag EndProperty	#tag Property, Flags = &h0		allowedQaLevels() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedQaOrigins() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedTargetStates() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedUtxSrcPoS() As string	#tag EndProperty	#tag Property, Flags = &h0		allowedUtxTgtStates() As string	#tag EndProperty	#tag Property, Flags = &h0		errorsEncountered As boolean	#tag EndProperty	#tag Property, Flags = &h0		myErrors() As XLIFFdocError	#tag EndProperty	#tag Property, Flags = &h0		myXLIFFxml As XmlDocument	#tag EndProperty	#tag Constant, Name = ALT_TRANS_TYPE_PROPOSAL, Type = String, Dynamic = False, Default = \"embedded match", Scope = Public	#tag EndConstant	#tag Constant, Name = ALT_TRANS_TYPE_VERSION_HISTORY, Type = String, Dynamic = False, Default = \"version history", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_ALT_TRANS_ELEMENT, Type = String, Dynamic = False, Default = \"<alt-trans> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DISALLOWED_ELEMENTS, Type = String, Dynamic = False, Default = \"Prohibited XLIFF 1.2 Elements Found", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DX_CONTEXT_ELEMENTS, Type = String, Dynamic = False, Default = \"<dx:context> element & children", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DX_NOTE_ELEMENT, Type = String, Dynamic = False, Default = \"<dx:note> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DX_QA_HIT_ELEMENT, Type = String, Dynamic = False, Default = \"<dx:qa-hit> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DX_UTX_GLOSSARY_ELEMENT, Type = String, Dynamic = False, Default = \"<dx:utx-glossary> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DX_UTX_SRC_ELEMENT, Type = String, Dynamic = False, Default = \"<dx:utx-src> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DX_UTX_TERM_ELEMENT, Type = String, Dynamic = False, Default = \"<dx:utx-term> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_DX_UTX_TGT_ELEMENT, Type = String, Dynamic = False, Default = \"<dx:utx-tgt> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_FILE_ELEMENT, Type = String, Dynamic = False, Default = \"<file> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_GROUP_ELEMENT, Type = String, Dynamic = False, Default = \"<group> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_G_ELEMENT, Type = String, Dynamic = False, Default = \"<g> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_INTERNAL_PREVIEW, Type = String, Dynamic = False, Default = \"<dx:internal-preview> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_MRK_ELEMENT, Type = String, Dynamic = False, Default = \"<mrk> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_PLACEHOLDER_ELEMENTS, Type = String, Dynamic = False, Default = \"<x> + <g> elements", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_TARGET_ELEMENT, Type = String, Dynamic = False, Default = \"<target> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_TU_ELEMENT, Type = String, Dynamic = False, Default = \"<trans-unit> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_VERSION, Type = String, Dynamic = False, Default = \"XLIFF:doc Version", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_CATEGORY_X_ELEMENT, Type = String, Dynamic = False, Default = \"<x> element", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_LEVEL_ERROR, Type = Double, Dynamic = False, Default = \"0", Scope = Public	#tag EndConstant	#tag Constant, Name = ERROR_LEVEL_WARNING, Type = Double, Dynamic = False, Default = \"1", Scope = Public	#tag EndConstant	#tag Constant, Name = STATE_BACKCHECK_COMPLETE, Type = String, Dynamic = False, Default = \"final", Scope = Public	#tag EndConstant	#tag Constant, Name = STATE_NEW, Type = String, Dynamic = False, Default = \"new", Scope = Public	#tag EndConstant	#tag Constant, Name = STATE_REJECTED, Type = String, Dynamic = False, Default = \"needs-review-translation", Scope = Public	#tag EndConstant	#tag Constant, Name = STATE_TRANSLATED, Type = String, Dynamic = False, Default = \"translated", Scope = Public	#tag EndConstant	#tag Constant, Name = STATE_VALIDATED, Type = String, Dynamic = False, Default = \"signed-off", Scope = Public	#tag EndConstant	#tag ViewBehavior		#tag ViewProperty			Name="errorsEncountered"			Group="Behavior"			Type="boolean"		#tag EndViewProperty		#tag ViewProperty			Name="Index"			Visible=true			Group="ID"			InitialValue="-2147483648"			InheritedFrom="Object"		#tag EndViewProperty		#tag ViewProperty			Name="Left"			Visible=true			Group="Position"			InitialValue="0"			InheritedFrom="Object"		#tag EndViewProperty		#tag ViewProperty			Name="Name"			Visible=true			Group="ID"			InheritedFrom="Object"		#tag EndViewProperty		#tag ViewProperty			Name="Super"			Visible=true			Group="ID"			InheritedFrom="Object"		#tag EndViewProperty		#tag ViewProperty			Name="Top"			Visible=true			Group="Position"			InitialValue="0"			InheritedFrom="Object"		#tag EndViewProperty	#tag EndViewBehaviorEnd Class#tag EndClass